package com.ruicar.afs.cloud.afscase.approvetask.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.ruicar.afs.cloud.afscase.approvemakelabel.entity.ApproveMakeLabel;
import com.ruicar.afs.cloud.afscase.approvemakelabel.service.ApproveMakeLabelService;
import com.ruicar.afs.cloud.afscase.approvetask.condition.ApproveCondition;
import com.ruicar.afs.cloud.afscase.approvetask.condition.WorkTaskPoolCondition;
import com.ruicar.afs.cloud.afscase.approvetask.entity.CaseApproveRecord;
import com.ruicar.afs.cloud.afscase.approvetask.entity.WorkProcessScheduleInfo;
import com.ruicar.afs.cloud.afscase.approvetask.entity.WorkProcessScheduleInfoTemp;
import com.ruicar.afs.cloud.afscase.approvetask.entity.WorkTaskPool;
import com.ruicar.afs.cloud.afscase.approvetask.service.*;
import com.ruicar.afs.cloud.afscase.approvetask.vo.*;
import com.ruicar.afs.cloud.afscase.common.utils.Const;
import com.ruicar.afs.cloud.afscase.creditoption.entity.CreditOptionInfo;
import com.ruicar.afs.cloud.afscase.creditoption.service.CreditOptionInfoService;
import com.ruicar.afs.cloud.afscase.dispatch.service.impl.DispatchServcieImpl;
import com.ruicar.afs.cloud.afscase.infomanagement.entity.CaseBaseInfo;
import com.ruicar.afs.cloud.afscase.infomanagement.entity.CaseCarInfo;
import com.ruicar.afs.cloud.afscase.infomanagement.entity.CaseRedundantInfo;
import com.ruicar.afs.cloud.afscase.infomanagement.service.CaseBaseInfoService;
import com.ruicar.afs.cloud.afscase.infomanagement.service.CaseCarInfoService;
import com.ruicar.afs.cloud.afscase.infomanagement.service.CaseCostInfoService;
import com.ruicar.afs.cloud.afscase.infomanagement.service.CaseRedundantInfoService;
import com.ruicar.afs.cloud.afscase.message.entity.CaseNoticeInfo;
import com.ruicar.afs.cloud.afscase.message.service.CaseNoticeInfoService;
import com.ruicar.afs.cloud.afscase.mq.approvesendinfo.service.ApproveInformInfoService;
import com.ruicar.afs.cloud.afscase.paramconfmanagement.entity.CaseConfParam;
import com.ruicar.afs.cloud.afscase.paramconfmanagement.service.CaseConfParamService;
import com.ruicar.afs.cloud.afscase.processor.enums.NormalSubmitType;
import com.ruicar.afs.cloud.afscase.processor.enums.WorkflowType;
import com.ruicar.afs.cloud.afscase.processor.service.ApproveWorkflowService;
import com.ruicar.afs.cloud.afscase.processor.vo.NormalReformistVO;
import com.ruicar.afs.cloud.afscase.processor.vo.NormalTaskSubmitVO;
import com.ruicar.afs.cloud.afscase.remind.entity.CaseRemindDetail;
import com.ruicar.afs.cloud.afscase.remind.service.RemindService;
import com.ruicar.afs.cloud.afscase.risk.service.DayBookResolveService;
import com.ruicar.afs.cloud.bizcommon.business.entity.FinCostDetails;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.security.util.SecurityUtils;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.core.util.SpringContextHolder;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.*;
import com.ruicar.afs.cloud.common.modules.dto.mq.approve.ApproveOpenDto;
import com.ruicar.afs.cloud.components.datadicsync.DicHelper;
import com.ruicar.afs.cloud.components.datadicsync.dto.DicDataDto;
import com.ruicar.afs.cloud.seats.condition.SysUserDto;
import com.ruicar.afs.cloud.seats.entity.UserCollocation;
import com.ruicar.afs.cloud.seats.feign.UserDetailsInfoFeign;
import com.ruicar.afs.cloud.seats.service.UserCollocationService;
import com.ruicar.afs.cloud.seats.util.PostStatus;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.WorkFlowResponse;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.request.QueryFLowCmdRequest;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.response.FlowCmdBean;
import com.ruicar.afs.cloud.workflow.gwt.service.WorkflowService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>Description: 审批代办件
 *
 * @author jiaqi.guo
 * @version 1.0
 * @date create on 2020-05-17 10:45
 */
@Slf4j
@RestController
@AllArgsConstructor
@Api("审核任务")
@RequestMapping("/approve")
public class ApproveTaskController {

    private WorkTaskPoolService workTaskPoolService;

    private CaseCarInfoService caseCarInfoService;


    private CaseBaseInfoService caseBaseInfoService;

    private ApproveMakeLabelService approveMakeLabelService;

    private CaseApproveRecordService caseApproveRecordService;
    private CreditOptionInfoService creditOptionInfoService;
    private WorkProcessScheduleInfoService workProcessScheduleInfoService;
    private WorkProcessScheduleInfoTempService workProcessScheduleInfoTempService;
    private ApproveInformInfoService approveInformInfoService;
    private UserCollocationService userCollocationService;
    private UserDetailsInfoFeign userDetailsInfoFeign;
    private CaseConfParamService caseConfParamService;
    private ApproveWorkflowService approveWorkflowService;
    private WorkflowService workflowService;
    private DayBookResolveService dayBookResolveService;
    private CaseNoticeInfoService caseNoticeInfoService;
    private WorkTaskPoolHistoryService workTaskPoolHistoryService;
    private ApproveInformInfoService informInfoService;
    private RemindService remindService;
    private CaseRedundantInfoService redundantInfoService ;
    private CaseCostInfoService caseCostInfoService;

    @PostMapping(value = "/queryApproveTaskList")
    @ApiOperation(value = "多条件分页获取待审核任务--仅展示当前登录用户的待审核任务，组长可以查看本组")
    public IResponse<IPage<ApproveTaskVo>> queryApproveTaskList(@ModelAttribute WorkTaskPoolCondition condition) {
        //流程类型条件
        List processList = new ArrayList();
        processList.add(ProcessTypeEnum.FORMAL_REVIEW.getCode());
        processList.add(ProcessTypeEnum.GENERA_APPROVE.getCode());
        processList.add(ProcessTypeEnum.INVENTORIES_ARE.getCode());
        processList.add(ProcessTypeEnum.SECONDARY_FRAUD.getCode());
        condition.setProcessTypeList(processList);

        //业务状态（内）
        List statusList = new ArrayList();
        statusList.add(AfsEnumUtil.key(BusinessStateInEnum.APPROVED));
        statusList.add(AfsEnumUtil.key(BusinessStateInEnum.CONDITIONAL_APPROVE));
        statusList.add(AfsEnumUtil.key(BusinessStateInEnum.REJECT));
        statusList.add(AfsEnumUtil.key(BusinessStateInEnum.REPEAL));
        statusList.add(AfsEnumUtil.key(BusinessStateInEnum.CANCEL_ADVICE_CONDITIONAL));
        condition.setBusinessStatusList(statusList);


        //特殊流程类型条件
        List processTypeSpecial = new ArrayList();
        processTypeSpecial.add(ProcessTypeEnum.CHANGE_ASSETS.getCode());
        processTypeSpecial.add(ProcessTypeEnum.RECONSIDER_APPLY.getCode());

        condition.setProcessTypeSpecial(processTypeSpecial);

        //特殊流程业务状态（内）
        List businessStatusSpecialList = new ArrayList();
        businessStatusSpecialList.add(AfsEnumUtil.key(BusinessStateInEnum.APPROVED));
        businessStatusSpecialList.add(AfsEnumUtil.key(BusinessStateInEnum.CONDITIONAL_APPROVE));
        businessStatusSpecialList.add(AfsEnumUtil.key(BusinessStateInEnum.REJECT));
        businessStatusSpecialList.add(AfsEnumUtil.key(BusinessStateInEnum.REPEAL));
        businessStatusSpecialList.add(AfsEnumUtil.key(BusinessStateInEnum.CANCEL_ADVICE_CONDITIONAL));
        condition.setBusinessStatusSpecialList(businessStatusSpecialList);

        //获取标签Id
        String[] str = condition.getTag();
        List labelIdList = new ArrayList();
          if (str!=null&&str.length>0) {
            for (int i = 0; i < str.length; i++) {
                labelIdList.add(str[i]);
            }
        }
        if (labelIdList != null && labelIdList.size() > 0) {
            condition.setLabelList(labelIdList);
        }
        //当前登录用户
        String useName = SecurityUtils.getUsername();
        condition.setDisposeStaff(useName);
        IPage<ApproveTaskVo> pageResult = workTaskPoolService.queryApproveTaskList(
                new Page(condition.getPageNumber(), condition.getPageSize()),
                condition);

        pageResult.getRecords().forEach(approveTaskVo -> {
            /**案件基础信息*/
            CaseBaseInfo caseBaseInfo = caseBaseInfoService.getOne(Wrappers.<CaseBaseInfo>query().lambda()
                    .eq(CaseBaseInfo::getApplyNo, approveTaskVo.getApplyNo()));
            /**车辆信息*/
            CaseCarInfo caseCarInfo = caseCarInfoService.getOne(Wrappers.<CaseCarInfo>query().lambda()
                    .eq(CaseCarInfo::getApplyNo, approveTaskVo.getApplyNo()));
            if (ObjectUtils.isNotEmpty(caseBaseInfo)) {
                // 当前时间，毫秒
                Long nowMilliSeconds = System.currentTimeMillis();
                // 开始时间，毫秒
                Long submitDateMilliSeconds = approveTaskVo.getStartTime().getTime();
                Long effectTimeReckon = caseBaseInfo.getEffectTimeReckon();
                int seconds = Convert.toInt((effectTimeReckon + nowMilliSeconds - submitDateMilliSeconds) / 1000, 0);
                String hour = StringUtils.leftPad(seconds / 3600 + "", 2, '0');
                String minute = StringUtils.leftPad((seconds % 3600) / 60 + "", 2, '0');
                String second = StringUtils.leftPad((seconds % 3600) % 60 + "", 2, '0');
                // 原始读秒
                approveTaskVo.setOriginalSeconds(seconds);
                // 计时时间，页面初始化时显示
                approveTaskVo.setTimming(hour + " : " + minute + " : " + second);
                // 拼接车辆信息显示
            }
            if (Objects.nonNull(caseCarInfo)) {
                approveTaskVo.setCarName(caseCarInfo.getModelName());
            }
            /**  标签信息 **/
            List<ApproveMakeLabel> labelList = approveMakeLabelService.list(Wrappers.<ApproveMakeLabel>query().lambda()
                    .eq(ApproveMakeLabel::getApplyNo, approveTaskVo.getApplyNo())
                    .eq(ApproveMakeLabel::getLabelLocation, LabelPositionEnum.LIST.getCode()));
            approveTaskVo.setLabelList(labelList);

            /** 流程信息 */
            WorkProcessScheduleInfo info = workProcessScheduleInfoService.getById(approveTaskVo.getStageId());
            if (Objects.nonNull(info)) {
                approveTaskVo.setFirstTrail(WhetherEnum.YES.getCode().equalsIgnoreCase(info.getFirstTrail()));
                approveTaskVo.setLastTrail(WhetherEnum.YES.getCode().equalsIgnoreCase(info.getLastTrail()));
            }
            if(AfsEnumUtil.key(BusinessStateInEnum.PAUSE).equals(approveTaskVo.getBusinessStatusIn())) {
                // 暂停原因
                Optional<CaseRemindDetail> remindDetailOptional = remindService.queryNewestRemindOpt(approveTaskVo.getApplyNo());
                if (remindDetailOptional.isPresent()) {
                    approveTaskVo.setParseMessage(remindDetailOptional.get().getRemindContent());
                }
            }
        });
        return IResponse.success(pageResult);

    }

    @PostMapping(value = "/queryApproveTaskSummary")
    @ApiOperation(value = "查询审批任务概要信息")
    public IResponse<ApproveTaskVo> queryApproveTaskSummary(@ModelAttribute WorkTaskPoolCondition workTaskPoolCondition) {
        List<WorkTaskPool> workTaskPoolList = workTaskPoolService.list(Wrappers.<WorkTaskPool>query().lambda()
                .eq(WorkTaskPool::getApplyNo, workTaskPoolCondition.getApplyNo()));

        ApproveTaskVo approveTaskVo = new ApproveTaskVo();
        if (ObjectUtils.isNotEmpty(workTaskPoolList)) {

            BeanUtils.copyProperties(workTaskPoolList.get(0), approveTaskVo);

            /**  标签信息 **/
            List<ApproveMakeLabel> labelList = approveMakeLabelService.list(Wrappers.<ApproveMakeLabel>query().lambda()
                    .eq(ApproveMakeLabel::getApplyNo, workTaskPoolList.get(0).getApplyNo())
                    .eq(ApproveMakeLabel::getLabelLocation, LabelPositionEnum.CREDITANALYSIS.getCode())
            );
            approveTaskVo.setLabelList(labelList);
        }
        return IResponse.success(approveTaskVo);
    }

    @GetMapping("/queryApprove")
    @ApiOperation("暂存审批意见查询")
    public IResponse queryApprove(@ModelAttribute ApproveCondition approveCondition) {
        WorkTaskPool workTaskPool = workTaskPoolService.getOne(
                Wrappers.<WorkTaskPool>lambdaQuery()
                        .eq(WorkTaskPool::getApplyNo, approveCondition.getApplyNo())
                        .eq(WorkTaskPool::getStageId, approveCondition.getStageId())
        );
        if (Objects.nonNull(workTaskPool)) {
            String remainDataStr = workTaskPool.getRemainData();
            ApproveRecordVO record = new ApproveRecordVO();
            record.setApplyNo(approveCondition.getApplyNo());
            record.setStageId(approveCondition.getStageId());
            if (StringUtils.isNotBlank(remainDataStr)) {
                JSONObject remainJson = JSONObject.parseObject(remainDataStr);
                if (remainJson.containsKey(AfsEnumUtil.key(RemainKeyEnum.RECORD))) {
                    record = JSONObject.parseObject(remainJson.get(AfsEnumUtil.key(RemainKeyEnum.RECORD)).toString(), ApproveRecordVO.class);
                    record.setQueried(true);
                }
            }
            return IResponse.success(record);
        } else {
            return IResponse.success("");
        }
    }

    @GetMapping("/querySomeApprove")
    @ApiOperation("已出结果案件信贷报告展示")
    public IResponse querySomeApprove(@ModelAttribute ApproveCondition approveCondition) {
        CaseBaseInfo caseBaseInfo = caseBaseInfoService.getOne(
                Wrappers.<CaseBaseInfo>lambdaQuery()
                .eq(CaseBaseInfo::getApplyNo,approveCondition.getApplyNo())
        );

        String businessStateIn = caseBaseInfo.getBusinessStateIn();
        if (businessStateIn.equals(AfsEnumUtil.key(BusinessStateInEnum.APPROVED)) || businessStateIn.equals(AfsEnumUtil.key(BusinessStateInEnum.REJECT))
        || businessStateIn.equals(AfsEnumUtil.key(BusinessStateInEnum.REPEAL)) || businessStateIn.equals(AfsEnumUtil.key(BusinessStateInEnum.CONDITIONAL_APPROVE))) {

            List<WorkTaskPool> workTaskPoolList = workTaskPoolService.list(
                    Wrappers.<WorkTaskPool>query().lambda()
                            .eq(WorkTaskPool::getApplyNo,approveCondition.getApplyNo())
                            .orderByDesc(WorkTaskPool::getCreateTime));
            if (CollectionUtil.isNotEmpty(workTaskPoolList)) {
                WorkTaskPool workTaskPool = workTaskPoolList.get(0);
                if (Objects.nonNull(workTaskPool)) {
                    String remainDataStr = workTaskPool.getRemainData();
                    CaseApproveRecord record = new CaseApproveRecord();
                    record.setApplyNo(approveCondition.getApplyNo());
                    record.setStageId(approveCondition.getStageId());
                    if (StringUtils.isNotBlank(remainDataStr)) {
                        JSONObject remainJson = JSONObject.parseObject(remainDataStr);
                        if (remainJson.containsKey(AfsEnumUtil.key(RemainKeyEnum.RECORD))) {
                            record = JSONObject.parseObject(remainJson.get(AfsEnumUtil.key(RemainKeyEnum.RECORD)).toString(), CaseApproveRecord.class);
                        }
                    }
                    return IResponse.success(record);
                } else {
                    return IResponse.success("");
                }
            }
        }
        return IResponse.success("");
    }

    @PostMapping("/saveApprove")
    @ApiOperation("信贷分析暂存")
    @Transactional
    public IResponse saveApprove(@RequestBody ApproveSubmitVO approveSubmitVO) {
        List<CreditOptionInfo> creditOptionInfos = approveSubmitVO.getCreditOptionInfos();
        if (CollectionUtil.isNotEmpty(creditOptionInfos)) {
            creditOptionInfoService.saveOrUpdateBatch(creditOptionInfos);
        }
        CaseApproveRecord caseApproveRecord = approveSubmitVO.getApproveRecord();
        if (Objects.nonNull(caseApproveRecord)) {
            WorkTaskPool workTaskPool = workTaskPoolService.getOne(
                    Wrappers.<WorkTaskPool>lambdaQuery()
                            .eq(WorkTaskPool::getApplyNo, caseApproveRecord.getApplyNo())
                            .eq(WorkTaskPool::getStageId, caseApproveRecord.getStageId())
            );
            // 暂存数据
            JSONObject jsonObject = new JSONObject();
            if (StringUtils.isNotBlank(workTaskPool.getRemainData())) {
                jsonObject = JSONObject.parseObject(workTaskPool.getRemainData());
            }
            jsonObject.put(AfsEnumUtil.key(RemainKeyEnum.RECORD), JSONObject.toJSON(caseApproveRecord));
            workTaskPool.setRemainData(jsonObject.toString());
            workTaskPoolService.updateById(workTaskPool);
        }
        return IResponse.success(approveSubmitVO);
    }

    @PostMapping("submitApprove")
    @ApiOperation("信贷分析提交审批")
    public IResponse submitApprove(@RequestBody ApproveSubmitVO approveSubmitVO) {
        CaseApproveRecord caseApproveRecord = approveSubmitVO.getApproveRecord();

        BigDecimal oldMonthPayAmt=this.getOldMonthPayAmt(caseApproveRecord.getApplyNo());

        FinCostDetails finCostDetails=caseCostInfoService.getOne(Wrappers.<FinCostDetails>query().lambda()
                .eq(FinCostDetails::getApplyNo,caseApproveRecord.getApplyNo())
                .eq(FinCostDetails::getCostType,CostTypeEnum.CARAMT.getCode()));
        if(oldMonthPayAmt.compareTo(finCostDetails.getMonthPayAmt())!=0&&
                !caseApproveRecord.getApproveSuggest().equals("suggestConditionF")&&
                !caseApproveRecord.getApproveSuggest().equals("suggestCondition")){
            throw  new  AfsBaseException("本案件已进行附条件操作,请选择相应审批建议!");
        }
        List<CreditOptionInfo> creditOptionInfos = approveSubmitVO.getCreditOptionInfos();
        if (CollectionUtil.isNotEmpty(creditOptionInfos)) {
            creditOptionInfoService.saveOrUpdateBatch(creditOptionInfos);
        }
        WorkProcessScheduleInfo info = workProcessScheduleInfoService.getById(caseApproveRecord.getStageId());
        caseApproveRecord.setUseScene(UseSceneEnum.APPROVE.getValue());
        caseApproveRecord.setApproveType(ApproveTypeEnum.PROCESS.getValue());
        approveWorkflowService.submit(NormalTaskSubmitVO.builder().record(caseApproveRecord).workFlowInfo(info).build());
        return IResponse.success("提交成功");
    }

    @GetMapping("/testWorkflow")
    public IResponse testWorkflow(@ModelAttribute ApproveCondition approveCondition) {
        WorkProcessScheduleInfoTemp info = testStart(approveCondition);
        approveWorkflowService.start(info);
        return IResponse.success("SUCCESS");
    }

    @Transactional
    public WorkProcessScheduleInfoTemp testStart(ApproveCondition approveCondition) {
        // 保存工作流实例
        WorkProcessScheduleInfoTemp info = new WorkProcessScheduleInfoTemp();
        info.setAfsFlowKey(WorkflowType.NORMAL_NEW.getAfsFlowKey());
        info.setApplyNo(approveCondition.getApplyNo());
        info.setProcessName(approveCondition.getApplyNo() + "常规审批测试");
        info.setStartTime(new Date());
        workProcessScheduleInfoTempService.save(info);;
        return info;
    }

    /**
     * @Description 查询当前操作组所有人员
     * @Author Peng_Jinbo
     * @Date 2020/7/7 18:21
     */
    @GetMapping("/listTaskHandler")
/*    @PreAuthorize("@pms.hasPermission('approve_handler_change')")*/
    public IResponse getNodeHandler() {
        CaseConfParam param = caseConfParamService.getOne(
                Wrappers.<CaseConfParam>lambdaQuery()
                        .eq(CaseConfParam::getParamType, Const.PARAMS_TASK_QUERY_DEPARTMENT)
        );
        if (Objects.isNull(param)) {
            return IResponse.fail("任务改派部门参数不存在，请先维护当前参数");
        }
        IResponse<List<SysUserDto>> response = userDetailsInfoFeign.getUsersByDepartmentId(param.getParamValue());
        if (CommonConstants.SUCCESS.equals(response.getCode())) {
            List<UserCollocation> userCollocationList = userCollocationService.list();
            Map<String, String> userStatusMap = new HashMap<>();
            if (CollectionUtil.isNotEmpty(userCollocationList)) {
                for (UserCollocation userCollocation : userCollocationList) {
                    userStatusMap.put(userCollocation.getLoginName(), userCollocation.getPostStatus());
                }
            }
            List<SysUserDto> userDtoList = response.getData();
            List<TaskHandlerVO> taskHandlerVOList = new ArrayList<>(userDtoList.size());
            for (SysUserDto sysUserDto : userDtoList) {
                String status = userStatusMap.get(sysUserDto.getUsername());
                taskHandlerVOList.add(TaskHandlerVO.builder()
                        .staffName(sysUserDto.getUsername())
                        .staffRealName(sysUserDto.getUserRealName())
                        .postStatus(Objects.isNull(status) ? PostStatus.NO.getCode() : status).build());
            }
            List result = Lists.partition(taskHandlerVOList, 10);
            TaskHandlerPageVO pageVO = TaskHandlerPageVO.builder()
                    .dataTotal(taskHandlerVOList.size())
                    .pageList(result)
                    .allDataList(taskHandlerVOList).build();
            return IResponse.success(pageVO);
        } else {
            return IResponse.fail(response.getMsg());
        }
    }

    /**
     * @Description 任务操作人变更
     * @Author Peng_Jinbo
     * @Date 2020/7/7 20:41taskPool
     */
    @PostMapping("/taskHandler")
//    @PreAuthorize("@pms.hasPermission('approve_handler_change')")
    public IResponse taskHandler(@RequestBody TaskHandlerChangeVO taskHandlerChangeVO) {
        return IResponse.success(approveWorkflowService.reformist(NormalReformistVO.builder()
                .stageId(taskHandlerChangeVO.getStageId())
                .reformistUserName(taskHandlerChangeVO.getUserName())
                .reformistUserRealName(taskHandlerChangeVO.getUserRealName())
                .oriUserName(taskHandlerChangeVO.getOriUserName()).build()).getMessage());
    }

    /**
    * @Description 流水解析调用
    * @Author Peng_Jinbo
    * @Date 2020/8/31 22:07
    */
    @GetMapping("/dayBookResolve")
    public IResponse dayBookResolve(@RequestParam("applyNo")String applyNo){
        dayBookResolveService.getDayBookResolve(applyNo);
        return IResponse.success("操作成功!");
    }

    /**
     * @Description 流程撤销
     * @Author Peng_Jinbo
     * @Date 2020/7/22 16:48
     */
    @PostMapping("/cancelFlow")
    public IResponse cancelFlow(@RequestBody WorkflowCancelVO cancelVO) {
        approveWorkflowService.cancelFlow(cancelVO.getStageId(), cancelVO.getMessage());
        return IResponse.success("操作成功");
    }


    /**
     * @Description 指定处理人流程发起
     * @Author Peng_Jinbo
     * @Date 2020/7/23 19:43
     */
    @PostMapping("/appointFlow")
    @Transactional
    public IResponse appointFlow(@RequestBody WorkflowAppointVO appointVO) {
        /**
         * 当案件处于待分配状态时，此时进行指定处理人时：
         * 1.首先会尝试获取分单定时任务的锁，获取失败时代表当前分单任务正在执行，抛出异常提示
         * 2.成功获得锁后会进行指定处理人操作，处理完毕或异常后释放锁
         */
        boolean hasLock = false;
        try {
            CaseBaseInfo baseInfo = caseBaseInfoService.getOne(
                    Wrappers.<CaseBaseInfo>lambdaQuery()
                            .eq(CaseBaseInfo::getApplyNo, appointVO.getApplyNo())
            );
            if (AfsEnumUtil.key(BusinessStateInEnum.ALLOCATION).equals(baseInfo.getBusinessStateIn())
                    || AfsEnumUtil.key(BusinessStateInEnum.TASK_ASSIGN).equals(baseInfo.getBusinessStateIn())) {
                if (AfsEnumUtil.key(BusinessStateInEnum.TASK_ASSIGN).equals(baseInfo.getBusinessStateIn())) {
                    approveWorkflowService.cancelFlow(baseInfo.getNormalApproveFlowId(), "任务未成功分配，废弃当前流程，发起指定处理人流程", false);
                    // 清除流程异常状态信息
                    baseInfo.setFlowParseId("");
                    baseInfo.setFlowParseType("");
                    baseInfo.setFlowParseExceptionId("");
                    baseInfo.setFlowParseFlag(WhetherEnum.NO.getCode());
                    caseBaseInfoService.updateById(baseInfo);
                }else if(AfsEnumUtil.key(BusinessStateInEnum.ALLOCATION).equals(baseInfo.getBusinessStateIn())){
                    if(SpringContextHolder.getBean(DispatchServcieImpl.class).tryLock()){
                        log.info("获取分单任务锁成功，进行执行指定处理人操作");
                        hasLock = true;
                    }else{
                        throw new AfsBaseException("指定处理人失败：当前分单任务正在执行，请稍后重试");
                    }
                }
                caseApproveRecordService.appoint(appointVO.getApplyNo());
                WorkProcessScheduleInfoTemp temp = new WorkProcessScheduleInfoTemp();
                temp.setAfsFlowKey(WorkflowType.NORMAL_APPOINT.getAfsFlowKey());
                temp.setApplyNo(appointVO.getApplyNo());
                temp.setAppointHandler(appointVO.getAppointStaff());
                workProcessScheduleInfoTempService.saveWithNewTransactional(temp);
                approveWorkflowService.start(temp);
                return IResponse.success("操作成功");
            } else {
                throw new AfsBaseException("当前任务已分配，无法进行指定处理人流程发起");
            }
        }finally {
            if(hasLock){
                log.info("指定处理人执行完毕，清除分单任务锁");
                SpringContextHolder.getBean(DispatchServcieImpl.class).unLock();
            }
        }
    }

    /**
     * 流程撤回
     * @author ma_xueyu
     * @date 2020年8月18日
     */
    @PostMapping("/callBackFlow")
    @Transactional
    public IResponse callBackFlow(@RequestBody WorkflowCallBackVO callBackVO) {
        WorkProcessScheduleInfo workProcessScheduleInfo = workProcessScheduleInfoService.getById(callBackVO.getScheduleId());
        CaseBaseInfo baseInfo = caseBaseInfoService.getOne(
                Wrappers.<CaseBaseInfo>lambdaQuery()
                        .eq(CaseBaseInfo::getApplyNo, workProcessScheduleInfo.getApplyNo())
        );
        String callBackApproveStaff=SecurityUtils.getUsername();
        String callBackApproveRealName = SecurityUtils.getUser().getUserRealName();
        //根据审批历史记录执行撤回校验
        boolean callbackCheckResult=workTaskPoolHistoryService.checkCallBackData(baseInfo,callBackVO.getScheduleId(),callBackApproveStaff);
        if(callbackCheckResult){

            //#################审批出结果后撤回###############
            if(AfsEnumUtil.key(BusinessStateInEnum.APPROVED).equals(baseInfo.getBusinessStateIn())
                    ||AfsEnumUtil.key(BusinessStateInEnum.CONDITIONAL_APPROVE).equals(baseInfo.getBusinessStateIn())){
                /** TODO 通知进件系统撤销核准数据 **/
                return IResponse.fail("暂不支持核准后撤回，请期待后续更新……");
            }

            //#################修订暂停状态下撤回#############
            else if(AfsEnumUtil.key(BusinessStateInEnum.REVISE_PARSE).equals(baseInfo.getBusinessStateIn())){
                log.info("通知进件系统撤回案件信息************");
                approveInformInfoService.submitApproveCallBackApply(baseInfo.getApplyNo(),baseInfo.getBusinessStateIn(),callBackVO.getScheduleId());
                try {
                    Thread.sleep(2000);
                }catch (InterruptedException e){
                    log.error("发生异常",e);
                }
                baseInfo = caseBaseInfoService.getOne(Wrappers.<CaseBaseInfo>lambdaQuery()
                                .eq(CaseBaseInfo::getApplyNo, workProcessScheduleInfo.getApplyNo()));
                if(AfsEnumUtil.key(BusinessStateInEnum.REVOCATION).equals(baseInfo.getBusinessStateIn())){
                    return IResponse.success("撤回成功！");
                }else{
                    return IResponse.fail("撤回失败,您也可稍后重试");
                }
            }

            //#################审批内部撤回##########################
            else{
                approveWorkflowService.callBackFlow(callBackVO.getScheduleId(),callBackVO.getMessage(),callBackApproveStaff,callBackApproveRealName);
            }
            return IResponse.success("撤回成功");
        }else{
            //#################未能直接撤回，保存撤回申请消息#############
            WorkTaskPool nextWorkTask = workTaskPoolService.getNextWorkTaskByCondition(workProcessScheduleInfo.getApplyNo(),callBackVO.getScheduleId(),callBackApproveStaff);
            CaseNoticeInfo caseNoticeInfo = new CaseNoticeInfo();
            caseNoticeInfo.setApplyNo(workProcessScheduleInfo.getApplyNo());
            caseNoticeInfo.setNoticeType(AfsEnumUtil.key(CallBackTypeEnum.WORKFLOW_APPROVER));
            caseNoticeInfo.setNotice("审批员【"+SecurityUtils.getUser().getUserRealName()+"】申请撤回提交，原因："+callBackVO.getMessage());
            caseNoticeInfo.setSendBy(callBackApproveStaff);
            caseNoticeInfo.setReceivedBy(nextWorkTask.getApproveStaff());
            caseNoticeInfo.setIsRead(AfsEnumUtil.key(ReadEnum.UNREAD));
            caseNoticeInfoService.save(caseNoticeInfo);
            return IResponse.fail("当前案件无法撤回");
        }
    }

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        dateFormat.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
    }

    /**
     * 查询常规审批流程下一节点任务是否是打开状态
     * @param stageId
     * */
    @GetMapping(value = "/getIsOpenByStageId/{stageId}")
    @ApiOperation(value = "查询常规审批流程下一节点任务是否是打开状态")
    public IResponse getIsOpenByStageId(@PathVariable(value = "stageId") String stageId) {
        WorkProcessScheduleInfo workProcessScheduleInfo = workProcessScheduleInfoService.getById(stageId);
        String callBackApproveStaff=SecurityUtils.getUsername();
        CaseBaseInfo caseBaseInfo = caseBaseInfoService.getOne(Wrappers.<CaseBaseInfo>query().lambda()
                .eq(CaseBaseInfo::getApplyNo, workProcessScheduleInfo.getApplyNo()));
        if(AfsEnumUtil.key(BusinessStateInEnum.REPEAL).equals(caseBaseInfo.getBusinessStateIn())
                ||AfsEnumUtil.key(BusinessStateInEnum.REJECT).equals(caseBaseInfo.getBusinessStateIn())){
            throw new AfsBaseException("已产生审批结果，无法撤回");
        }
        //根据审批历史记录执行撤回校验
        workTaskPoolHistoryService.checkCallBackData(caseBaseInfo,stageId,callBackApproveStaff);
        WorkTaskPool nextWorkTask = workTaskPoolService.getNextWorkTaskByCondition(workProcessScheduleInfo.getApplyNo(),stageId,callBackApproveStaff);
        return IResponse.success(nextWorkTask.getIsOpen());
    }
    /**
     * @description: 维护是否打开状态
     * @author jiaqi.guo
     * @created 2020/7/7 20:54
     * @version 1.0
     */
    @PostMapping("/setStatusIsOpen")
    @Transactional
    public IResponse setStatusIsOpen(@ModelAttribute ApproveCondition approveCondition) {
        WorkTaskPool workTaskPool = workTaskPoolService.getOne(Wrappers.<WorkTaskPool>query().lambda()
                .eq(WorkTaskPool::getApproveStaff, approveCondition.getApproveStaff())
                .eq(WorkTaskPool::getStageId, approveCondition.getStageId()));
       if(ObjectUtils.isNotEmpty(workTaskPool)){
           workTaskPool.setIsOpen(WhetherEnum.YES.getCode());
           log.info("更新是否打开状态：" + workTaskPool.getApproveStaff());
           workTaskPoolService.updateById(workTaskPool);
           ApproveOpenDto approveOpenDto=new ApproveOpenDto();
           approveOpenDto.setApplyNo(approveCondition.getApplyNo());
           approveOpenDto.setStageId(approveCondition.getStageId());
           approveOpenDto.setOpenTime(new Date());
           approveOpenDto.setOpenResult(WhetherEnum.YES.getCode());
           approveOpenDto.setProcessType(approveCondition.getProcessType());
           informInfoService.incomingApproveOpenResult(approveOpenDto);
           log.info("打开状态通知mq发送成功：{}" + approveCondition.getProcessType());
       }else{
           log.info("无流程信息更新失败！");
       }
        return IResponse.success("更新成功");
    }

    /**
    * @Description 获取当前节点可操作命令
    * @Author Peng_Jinbo
    * @Date 2020/9/24 14:26
    */
    @GetMapping("/getFlowCmd")
    public IResponse getFlowCmd(@RequestParam("stageId")String stageId){
        List<String> cmdList = new ArrayList<>();
        if(StringUtils.isNotBlank(stageId)) {
            WorkProcessScheduleInfo scheduleInfo = workProcessScheduleInfoService.getById(stageId);
            QueryFLowCmdRequest queryFLowCmdRequest = new QueryFLowCmdRequest();
            queryFLowCmdRequest.setFlowInstanceId(scheduleInfo.getStageId());
            WorkFlowResponse<List<FlowCmdBean>> cmdResponse = workflowService.queryFlowCmd(queryFLowCmdRequest);
            List<DicDataDto> dicDtoList = DicHelper.getDicMaps("approveSuggest").get("approveSuggest");
            if (CollectionUtil.isNotEmpty(dicDtoList)) {
                Map<String, DicDataDto> dicCmdMap = dicDtoList.stream().filter(
                        dic -> {
                            return !StringUtils.equals(dic.getValue(), AfsEnumUtil.key(NormalSubmitType.SEND_BACK))
                                    && !StringUtils.equals(dic.getValue(), AfsEnumUtil.key(NormalSubmitType.SEND_BACK_TO_DEALER));
                        }
                ).collect(Collectors.toMap(DicDataDto::getTitle, Function.identity()));
                ;
                if (Const.WORKFLOW_RESPONSE_SUCCESS == cmdResponse.getSuccess() && CollectionUtil.isNotEmpty(cmdResponse.getAfsData())) {
                    List<FlowCmdBean> gwtFlowList = cmdResponse.getAfsData();
                    gwtFlowList.stream()
                            .sorted(Comparator.nullsFirst(Comparator.comparing(FlowCmdBean::getOrderId)))
                            .filter(flowCmd -> StringUtils.isNotBlank(flowCmd.getCmdDis()) && dicCmdMap.keySet().contains(flowCmd.getCmdDis()))
                            .forEach(cmdBean -> cmdList.add(dicCmdMap.get(cmdBean.getCmdDis()).getValue()));
                }
            }
        }
        return IResponse.success(cmdList);
    }
    /**
     * @description: 获取附条件核准冗余首期月供
     * @author jiaqi.guo
     * @created 2020/9/27 21:28
     * @version 1.0
     */
    public BigDecimal getOldMonthPayAmt(String applyNo) {
        //add by gjq 附条件核准留痕
        CaseRedundantInfo redundantInfo= redundantInfoService.getOne(Wrappers.<CaseRedundantInfo>query().lambda()
                .eq(com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(applyNo),CaseRedundantInfo::getApplyNo,applyNo));
        JSONObject jsonObject=null;
        BigDecimal oldMonthPayAmt=BigDecimal.ZERO;
        if(ObjectUtils.isNotEmpty(redundantInfo)){
            String conditionalApproval=redundantInfo.getConditionalApproval();
            if(com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(conditionalApproval)){
                jsonObject= JSONObject.parseObject(conditionalApproval);
            }
        }
        //融资信息
        JSONArray costDetailsList = jsonObject.getJSONArray("finCostDetailsList");
        if (ObjectUtils.isNotEmpty(costDetailsList) && costDetailsList.size() > 0) {
            for (FinCostDetails finCostDetails : costDetailsList.toJavaList(FinCostDetails.class)) {
                if(finCostDetails.getCostType().equals(CostTypeEnum.CARAMT.getCode())){
                    oldMonthPayAmt=oldMonthPayAmt.add(finCostDetails.getMonthPayAmt());
                }
            }

        }
        return oldMonthPayAmt;
    }

    /**
     * 查询案件业务状态
     * @param applyNo 申请编号
     * @author maxueyu
     * @date 2020年10月13日
     * */
    @ApiOperation("查询案件业务状态")
    @GetMapping(value = "/getCaseBuinessStateInfo")
    IResponse getCaseBuinessStateInfo(@RequestParam("applyNo") String applyNo){
        CaseBaseInfo caseBaseInfo = caseBaseInfoService.getOne(Wrappers.<CaseBaseInfo>query().lambda()
                .eq(CaseBaseInfo::getApplyNo,applyNo));
        return IResponse.success(caseBaseInfo.getBusinessStateIn());
    }

}
